package util;

import entity.UserBean;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

public class JDBCUtil {

    static Properties prop = new Properties();

    static {
        // 读取属性文件
        try {
            prop.load(JDBCUtil.class.getClassLoader().getResourceAsStream("jdbc.properties"));
        } catch (IOException e) {
            throw new RuntimeException("数据库配制文件加载失败！"+e.getMessage());
        }
        //注册数据库连接驱动
        try {
            Class.forName(prop.getProperty("driver"));
        } catch (ClassNotFoundException e) {
            throw new RuntimeException("数据库驱动出错:"+e.getMessage());
        }
    }

    public static <T> List<T> list(String sql, Class<T> clazz, Object... parameters) {
        List<T> list = new ArrayList<>();
        try (Connection con = getCon()) {
            try (PreparedStatement stmt = con.prepareStatement(sql)) {
                /*动态替换参数*/
                int index = 1;
                for (Object param : parameters) {
                    stmt.setObject(index++, param);
                }

                ResultSet rs = stmt.executeQuery();
                while (rs.next()) {
                    list.add(getObject(clazz, rs));
                }
            } catch (InstantiationException e) {
                throw new RuntimeException("数据表中的数据映射到实现类对象失败:" + e.getMessage());
            }
        } catch (SQLException | IllegalAccessException | InvocationTargetException e) {
            throw new RuntimeException("数据表中的数据映射到实现类对象失败:" + e.getMessage());
        }
        return list;
    }

    public static <T> T one(String sql, Class<T> clazz, Object... parameters) {
        T t = null;
        try (Connection con = getCon()) {
            try (PreparedStatement stmt = con.prepareStatement(sql)) {
                /*动态替换参数*/
                int index = 1;
                for (Object param : parameters) {
                    stmt.setObject(index++, param);
                }
                ResultSet rs = stmt.executeQuery();
                if (rs.next()) {
                    t = getObject(clazz, rs);
                }
            } catch (InstantiationException e) {
                throw new RuntimeException("数据表中的数据映射到实现类对象失败:" + e.getMessage());
            }
        } catch (SQLException | IllegalAccessException | InvocationTargetException e) {
            throw new RuntimeException("数据表中的数据映射到实现类对象失败:" + e.getMessage());
        }
        return t;
    }

    private static <T> T getObject(Class<T> clazz, ResultSet rs) throws InstantiationException, IllegalAccessException, SQLException, InvocationTargetException {
        T t = clazz.newInstance();
        ResultSetMetaData metaData = rs.getMetaData();//获取结果集的元数据对象
        Method[] methods = clazz.getDeclaredMethods();//获取实体类中所有方法对象
        for (int i = 1; i <= metaData.getColumnCount(); i++)//根据结果集的列的数据循环
        {
            String fieldName = metaData.getColumnName(i);//获取第一个列的列名（列：数据库表中的列名)
            String methodName = "set" + fieldName.toUpperCase().substring(0, 1)
                    + fieldName.substring(1);//拼接set方法名(比：age=>setAge, userName=>setUserName
            for (Method m : methods) {
                if (m.getName().equals(methodName)) {
                    m.invoke(t, rs.getObject(fieldName));//执行指定方法
                    break;
                }
            }
            //正常方法执行  对象.方法名(实参)如： question.setName("axxx")
            //反向执行方法  方法对象.invoke(对象,实参)  如： mothod.invoke(qusetion,"axxx")
        }
        return t;
    }

    public static int update(String sql, Object... parameters) {
        int row = 0;
        try (Connection con = getCon()) {
            try (PreparedStatement stmt = con.prepareStatement(sql)) {
                /*动态替换参数*/
                int index = 1;
                for (Object param : parameters) {
                    stmt.setObject(index++, param);
                }
                row = stmt.executeUpdate();
            }
        } catch (SQLException e) {
            throw new RuntimeException("数据表更新失败:" + e.getMessage());
        }
        return row;
    }


    public static Connection getCon() {
        try {
            return DriverManager.getConnection(
                    prop.getProperty("url"),
                    prop.getProperty("uid"),
                    prop.getProperty("pwd")
            );
        } catch (SQLException e) {
            throw new RuntimeException("数据库连接出错："+e.getMessage());
        }
    }

    public static void main(String[] args) throws IOException {
        String sql = "SELECT uid,uname,eMail,uphone,urole,ustate FROM userList";
        List<UserBean> list = JDBCUtil.list(sql,UserBean.class);
        for (UserBean stu: list ) {
            System.out.println(stu.getRname());
        }
    }
}
